package com.maximus.server.nio.multithreadingReactor;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HandlerMulti implements Runnable {
    private static final Logger logger = LogManager.getLogger(HandlerMulti.class);

    private static final ExecutorService executors = Executors.newFixedThreadPool(3);
    private SocketChannel socketChannel;
    private ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    private StringBuilder buffer = new StringBuilder();
    private static final Charset CHARSET = StandardCharsets.UTF_8;

    public HandlerMulti(SocketChannel socketChannel) {
        this.socketChannel = socketChannel;
    }

    @Override
    public void run() {
        try {
            int bytesRead = socketChannel.read(readBuffer);
            if (bytesRead > 0) {
                readBuffer.flip();
                buffer.append(CHARSET.decode(readBuffer));
                readBuffer.clear();
                processBuffer();
            } else if (bytesRead == -1) {
                logger.info(socketChannel.getRemoteAddress() + "离线了...");
                socketChannel.close();
            }
        } catch (IOException e) {
            handleException(e);
        }
    }

    private void processBuffer() {
        int index;
        while ((index = findLineEnd(buffer)) != -1) {
            String line = extractLine(buffer, index);
            executors.execute(new Processor(socketChannel, line));
        }
    }

    private int findLineEnd(StringBuilder buffer) {
        String data = buffer.toString();
        int rnIndex = data.indexOf("\r\n");
        if (rnIndex != -1) return rnIndex + 2; // 包括\r\n的长度
        int nIndex = data.indexOf("\n");
        if (nIndex != -1) return nIndex + 1;    // 包括\n的长度
        return -1;
    }

    private String extractLine(StringBuilder buffer, int endIndex) {
        String line = buffer.substring(0, endIndex).trim();
        buffer.delete(0, endIndex);
        return line;
    }

    private void handleException(IOException e) {
        logger.info(e);
        try {
            socketChannel.close();
        } catch (IOException ex) {
            logger.info(ex);
        }
    }
}
